home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / prefix / child.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  32.9 KB  |  1,160 lines

  1. /***********************************************************************
  2.  *
  3.  * PROJECT:      PMake
  4.  * MODULE:      Prefix -- Child process
  5.  * FILE:      child.c
  6.  *
  7.  * AUTHOR:        Adam de Boor: Jul  9, 1989
  8.  *
  9.  * ROUTINES:
  10.  *    Name              Description
  11.  *    ----              -----------
  12.  *    Child_Init          Initialize the module
  13.  *    Child_Call          Perform a call to the child.
  14.  *    Child_MountSpecial  Mount a special directory locally to a different
  15.  *                        address with a special handle format
  16.  *    Child_Kill          Blow the child away.
  17.  *
  18.  * REVISION HISTORY:
  19.  *    Date      Name        Description
  20.  *    ----      ----        -----------
  21.  *    7/ 9/89      ardeb        Initial version
  22.  *
  23.  * DESCRIPTION:
  24.  *    This module and process exist only to mount and unmount
  25.  *    prefixes at the request of the parent process. Why? To prevent
  26.  *    deadlock, should the kernel need to talk to the parent during
  27.  *    the course of the mounting or unmounting (e.g. to lookup a
  28.  *    component on the way to the mount point).
  29.  *
  30.  *    As such, this beastie handles only four procedures arriving on
  31.  *    the childSock created by the parent and inherited by this process:
  32.  *    PREFIX_MOUNT, PREFIX_MOUNT_LOCAL, PREFIX_UNMOUNT and
  33.  *    PREFIX_UNMOUNT_LOCAL.
  34.  *
  35.  *     Copyright (c) Berkeley Softworks 1989
  36.  *     Copyright (c) Adam de Boor 1989
  37.  *
  38.  *     Permission to use, copy, modify, and distribute this
  39.  *     software and its documentation for any non-commercial purpose
  40.  *    and without fee is hereby granted, provided that the above copyright
  41.  *     notice appears in all copies.  Neither Berkeley Softworks nor
  42.  *     Adam de Boor makes any representations about the suitability of this
  43.  *     software for any purpose.  It is provided "as is" without
  44.  *     express or implied warranty.
  45.  *
  46.  ***********************************************************************/
  47. #ifndef lint
  48. static char *rcsid =
  49. "$Id: child.c,v 1.9 89/10/10 12:14:34 root Exp $";
  50. #endif lint
  51.  
  52. #include    "prefix.h"
  53. #include    "rpc.h"
  54.  
  55. #define    NFS         /* Want NFS mount parameters */
  56. #define NFSCLIENT   /* For SunOS 4.0... */
  57. #include    <sys/mount.h>
  58. #include    <rpcsvc/mount.h>
  59. #include    <mntent.h>
  60.  
  61. /*
  62.  * Take care of SunOS 4.0 stuff -- fs type is a string, not an int, and
  63.  * we have to pass the M_NEWTYPE flag (taken care of later)
  64.  */
  65. #ifndef MOUNT_NFS
  66. #define MOUNT_NFS   "nfs"
  67. #endif
  68.  
  69. static int                  childSock;        /* Socket on which the child will
  70.                          * listen (used only by child) */
  71. static struct sockaddr_in   childAddr;        /* Address of same */
  72. static int                  childID;        /* Process ID of child, in case
  73.                          * it needs to be nuked. */
  74.  
  75. static int                  mountdSock;        /* Privileged socket for talking
  76.                          * to mount daemons */
  77.  
  78. #define NUM_RETRIES     5        /* Number of times to try call. Needs to
  79.                      * be enough (coupled with a long enough
  80.                      * retry interval) to compensate for
  81.                      * contacting a remote mount daemon.
  82.                      * So far, a ten-second total time has
  83.                      * been sufficient. */
  84.  
  85.  
  86. #define CHILD_MAX_DATA    2048        /* Longest serverName, path, remote and
  87.                      * options can be */
  88.  
  89. /*
  90.  * Structure for call parameters. sin is address of remote server, for use
  91.  * in contacting the mount daemon. For both the mount and unmount
  92.  * calls, the serverName, path and remote fields of the prefix are copied
  93.  * into the data field, one after the other. For the mount call, the
  94.  * options are placed after this.
  95.  */
  96. typedef struct {
  97.     struct sockaddr_in    sin;                    /* Server address */
  98.     char                data[CHILD_MAX_DATA];    /* Other data */
  99. }    ChildData;
  100.  
  101.  
  102. /***********************************************************************
  103.  *                ChildCallMountd
  104.  ***********************************************************************
  105.  * SYNOPSIS:        Contact a remote mount daemon about a prefix
  106.  * CALLED BY:        ChildMount, ChildUnmount
  107.  * RETURN:        1 if successful.
  108.  * SIDE EFFECTS:    server->sin_port is replaced with mountd's port on
  109.  *                remote server.
  110.  *
  111.  * STRATEGY:
  112.  *    - Create a CLIENT handle to the remote daemon
  113.  *    - Perform the requested call, passing the prefix's remote
  114.  *      path as an argument.
  115.  *    - Return 1 if SUNRPC_SUCCESS came back from the call.
  116.  *
  117.  * REVISION HISTORY:
  118.  *    Name    Date        Description
  119.  *    ----    ----        -----------
  120.  *    ardeb    7/ 9/89        Initial Revision
  121.  *
  122.  ***********************************************************************/
  123. static int
  124. ChildCallMountd(server, serverName, remote, proc, xdrret, retdata)
  125.     struct sockaddr_in    *server;        /* Address of server */
  126.     char                *serverName;    /* Name of same */
  127.     char                *remote;        /* Name of remote directory about
  128.                      * which we're calling */
  129.     int                    proc;             /* Procedure to call */
  130.     xdrproc_t            xdrret;            /* Procedure to decode the result */
  131.     caddr_t             *retdata;       /* Place to store the result */
  132. {
  133.     struct timeval      timeout;    /* Interval for calling mount daemon */
  134.     enum clnt_stat      rpc_stat;   /* Result of calling */
  135.     AUTH                *auth;        /* Credentials -- created each time to
  136.                      * avoid problems with bogus short forms
  137.                      * going to remote mount daemons */
  138.  
  139.     /*
  140.      * Create client handle to the server's mountd, using
  141.      * a 2-second retrans interval and 10-second call timeout. The server
  142.      * field of the prefix has been filled with the address and family, but
  143.      * not the port, which we get from the portmapper on the remote machine by
  144.      * setting the port to 0.
  145.      */
  146.     timeout.tv_usec = 0;
  147.     timeout.tv_sec = 2;
  148.  
  149.     server->sin_port = 0;
  150.  
  151.     /*
  152.      * Also wants unix credentials (?!)
  153.      */
  154.     auth = authunix_create_default();
  155.  
  156.     /*
  157.      * Give the mount daemon 5 tries with a two-second retry interval...
  158.      */
  159.     rpc_stat = SunRpc_Call(mountdSock, server, auth,
  160.                MOUNTPROG, proc, MOUNTVERS,
  161.                xdr_path, &remote,
  162.                xdrret, retdata, NUM_RETRIES, &timeout);
  163.  
  164.     /*
  165.      * Don't need these any more...
  166.      */
  167.     auth_destroy(auth);
  168.     
  169.     return (rpc_stat == SUNRPC_SUCCESS);
  170. }
  171.  
  172.  
  173. /***********************************************************************
  174.  *                ChildFetchNumericOption
  175.  ***********************************************************************
  176.  * SYNOPSIS:        Fetch the value of a numeric option of the form
  177.  *                biff=n.
  178.  * CALLED BY:        ChildMount
  179.  * RETURN:        0 if the option not found or is hosed, else the value.
  180.  * SIDE EFFECTS:    None.
  181.  *
  182.  * STRATEGY:
  183.  *
  184.  * REVISION HISTORY:
  185.  *    Name    Date        Description
  186.  *    ----    ----        -----------
  187.  *    ardeb    7/ 8/89        Initial Revision
  188.  *
  189.  ***********************************************************************/
  190. static int
  191. ChildFetchNumericOption(mnt, opt)
  192.     struct mntent   *mnt;       /* Entry to search */
  193.     char            *opt;       /* Option desired */
  194. {
  195.     int             val=0;      /* Current value */
  196.     char            *equal;     /* Position of = sign */
  197.     char            *str;       /* Start of option */
  198.     
  199.     /*
  200.      * Locate the start of the option first.
  201.      */
  202.     str = hasmntopt(mnt, opt);
  203.     if (str != NULL) {
  204.     /*
  205.      * Option exists -- find the start of the value (just after the =)
  206.      */
  207.     equal = (char *)index(str, '=');
  208.  
  209.     if (equal != NULL) {
  210.         val = atoi(equal+1);
  211.     } else {
  212.         Message("ChildFetchNumericOption: bad numeric option '%s'\n", str);
  213.     }
  214.     }
  215.     return (val);
  216. }
  217.  
  218.  
  219. /***********************************************************************
  220.  *                ChildMount
  221.  ***********************************************************************
  222.  * SYNOPSIS:        Mount a remote filesystem
  223.  * CALLED BY:        PREFIX_MOUNT
  224.  * RETURN:        1 if mount successful
  225.  * SIDE EFFECTS:    An entry is placed in /etc/mtab if successful.
  226.  *
  227.  * STRATEGY:
  228.  *    There are several stages in the mounting of a remote system:
  229.  *        - contact the mount daemon on the remote machine to get
  230.  *          the all-important first handle for the root of the
  231.  *          desired file-system, a handle via which all the other
  232.  *          handles and files for the system can be gotten.
  233.  *        - put together a set of nfs_args to pass to the kernel,
  234.  *          based on the information (serverName, remote, path, options)
  235.  *          we were passed.
  236.  *        - try 10 times to mount the system.
  237.  *        - if successful, add an entry to /etc/mtab for the system
  238.  *          and return 1.
  239.  *        - else return 0
  240.  *
  241.  * REVISION HISTORY:
  242.  *    Name    Date        Description
  243.  *    ----    ----        -----------
  244.  *    ardeb    7/ 9/89        Initial Revision
  245.  *
  246.  ***********************************************************************/
  247. static void
  248. ChildMount(from, msg, len, data, serverData)
  249.     struct sockaddr_in    *from;        /* Source of call (s/b PREFIX_PORT) */
  250.     Rpc_Message            msg;        /* Message for reply/error */
  251.     int            len;        /* Length of passed data */
  252.     Rpc_Opaque            data;        /* Parameters (ChildData) */
  253.     Rpc_Opaque            serverData; /* Data we gave (UNUSED) */
  254. {
  255.     ChildData            *params;    /* Passed parameters */
  256.     struct fhstatus     fhs;        /* Result of call to mount daemon */
  257.     struct nfs_args     mount_args; /* Args for kernel mount call */
  258.     int                    flags;        /* General mount flags */
  259.     FILE            *mtab;        /* Stream open to /etc/mtab for
  260.                      * installing newly-mounted prefix */
  261.     struct mntent    entry;        /* New entry for /etc/mtab */
  262.     char            fsname[128];/* Name of remote FS for entry */
  263.     unsigned short      port;        /* Port number of NFS server */
  264.     int                    retval;        /* Value we're returning */
  265.     int                    tries;        /* Number of mount attempts */
  266.     /*
  267.      * Data extracted from params
  268.      */
  269.     char                *serverName;/* Name of server */
  270.     char                *remote;    /* Directory to mount */
  271.     char                *path;        /* Directory on which to mount it */
  272.     char                *options;   /* Options for the mount */
  273.  
  274.     /*
  275.      * Minimal security: Make sure came from the right port.
  276.      */
  277.     if ((ntohs(from->sin_port) != PREFIX_PORT) || !Rpc_IsLocal(from)) {
  278.     Rpc_Error(msg, RPC_ACCESS);
  279.     return;
  280.     }
  281.     
  282.     /*
  283.      * Extract needed info from parameters
  284.      */
  285.     params      = (ChildData *)data;
  286.     serverName     = params->data;
  287.     remote      = serverName + strlen(serverName) + 1;
  288.     path        = remote + strlen(remote) + 1;
  289.     options     = path + strlen(path) + 1;
  290.  
  291.     dprintf("ChildMount: mounting %s from %s[%s]: ", path, serverName, remote);
  292.     
  293.     /*
  294.      * Tell the kernel the name of the server
  295.      */
  296.     mount_args.flags = NFSMNT_HOSTNAME;
  297.     mount_args.hostname = serverName;
  298.  
  299.     /*
  300.      * Contact the remote daemon to get the initial file handle for the mount
  301.      */
  302.     if (!ChildCallMountd(¶ms->sin, serverName, remote, MOUNTPROC_MNT,
  303.              xdr_fhstatus, (caddr_t *)&fhs))
  304.     {
  305.     Message("ChildMount: couldn't contact %s's mount daemon", serverName);
  306. mount_error:
  307.     retval = 0;
  308.     Rpc_Return(msg, sizeof(retval), (Rpc_Opaque)&retval);
  309.     return;
  310.     }
  311.     
  312.     /*
  313.      * Check the return value (ChildCallMountd just returns the status
  314.      * of the message, not the results of the call...)
  315.      */
  316.     if (fhs.fhs_status == NFSERR_ACCES) {
  317.     Message("ChildMount: access denied for %s[%s]", serverName, remote);
  318.     goto mount_error;
  319.     } else if (fhs.fhs_status) {
  320.     /*
  321.      * Set errno to be the status returned so perror can get at it
  322.      */
  323.     errno = fhs.fhs_status;
  324.     perror("ChildMount");
  325.     goto mount_error;
  326.     }
  327.  
  328.     
  329.     /*
  330.      * Tell the kernel where to find the FS
  331.      */
  332.     mount_args.fh   = &fhs.fhs_fh;
  333.     mount_args.addr = ¶ms->sin;
  334.  
  335.     /*
  336.      * Set up the mount table entry and decode the options.
  337.      */
  338.     sprintf(fsname, "%s:%s", serverName, remote);
  339.  
  340.     entry.mnt_fsname     = fsname;
  341.     entry.mnt_dir       = path;
  342.     entry.mnt_type      = MNTTYPE_NFS;
  343.     entry.mnt_opts      = options;
  344.     entry.mnt_freq      = 0;
  345.     entry.mnt_passno     = 0;
  346.  
  347.     flags = 0;
  348.  
  349.     /*
  350.      * Take care of the universal flags first.
  351.      */
  352.     if (hasmntopt(&entry, MNTOPT_RO) != NULL) {
  353.     dprintf("rdonly ");
  354.     flags |= M_RDONLY;
  355.     }
  356.     if (hasmntopt(&entry, MNTOPT_NOSUID) != NULL) {
  357.     dprintf("nosuid ");
  358.     flags |= M_NOSUID;
  359.     }
  360. #ifdef MNTOPT_GRPID
  361.     /*
  362.      * SunOS 4.0 things...
  363.      */
  364.     flags |= M_NEWTYPE;
  365.     if (hasmntopt(&entry, MNTOPT_GRPID) != NULL) {
  366.     dprintf("grpid ");
  367.     flags |= M_GRPID;
  368.     }
  369.     if (hasmntopt(&entry, MNTOPT_NOSUB) != NULL) {
  370.     dprintf("nosub ");
  371.     flags |= M_NOSUB;
  372.     }
  373.     /*XXX: what to do about "secure"? Do we have to contact mountd with
  374.      * DES authentication? */
  375.     
  376.     if (mount_args.acregmin = ChildFetchNumericOption(&entry, "acregmin")) {
  377.     dprintf("acregmin=%d ", mount_args.acregmin);
  378.     mount_args.flags |= NFSMNT_ACREGMIN;
  379.     }
  380.  
  381.     if (mount_args.acregmax = ChildFetchNumericOption(&entry, "acregmax")) {
  382.     dprintf("acregmax=%d ", mount_args.acregmax);
  383.     mount_args.flags |= NFSMNT_ACREGMAX;
  384.     }
  385.  
  386.     if (mount_args.acdirmin = ChildFetchNumericOption(&entry, "acdirmin")) {
  387.     dprintf("acdirmin=%d ", mount_args.acdirmin);
  388.     mount_args.flags |= NFSMNT_ACDIRMIN;
  389.     }
  390.  
  391.     if (mount_args.acdirmax = ChildFetchNumericOption(&entry, "acdirmax")) {
  392.     dprintf("acdirmax=%d ", mount_args.acdirmax);
  393.     mount_args.flags |= NFSMNT_ACDIRMAX;
  394.     }
  395.  
  396.     if (hasmntopt(&entry, "noac") != NULL) {
  397.     mount_args.flags |= NFSMNT_NOAC;
  398.     }
  399. #endif /* MNTOPT_GRPID */
  400.  
  401.     /*
  402.      * Now the nfs-specific ones
  403.      */
  404.     if (hasmntopt(&entry, MNTOPT_SOFT) != NULL) {
  405.     dprintf("soft ");
  406.     mount_args.flags |= NFSMNT_SOFT;
  407.     }
  408.     if (hasmntopt(&entry, MNTOPT_INTR) != NULL) {
  409.     dprintf("intr ");
  410.     mount_args.flags |= NFSMNT_INT;
  411.     }
  412.     if (mount_args.rsize = ChildFetchNumericOption(&entry, "rsize")) {
  413.     dprintf("rsize=%d ", mount_args.rsize);
  414.     mount_args.flags |= NFSMNT_RSIZE;
  415.     }
  416.     if (mount_args.wsize = ChildFetchNumericOption(&entry, "wsize")) {
  417.     dprintf("wsize=%d ", mount_args.wsize);
  418.     mount_args.flags |= NFSMNT_WSIZE;
  419.     }
  420.     if (mount_args.timeo = ChildFetchNumericOption(&entry, "timeo")) {
  421.     dprintf("timeo=%d ", mount_args.timeo);
  422.     mount_args.flags |= NFSMNT_TIMEO;
  423.     }
  424.     if (mount_args.retrans = ChildFetchNumericOption(&entry, "retrans")) {
  425.     dprintf("retrans=%d ", mount_args.retrans);
  426.     mount_args.flags |= NFSMNT_RETRANS;
  427.     }
  428.     if (port = ChildFetchNumericOption(&entry, "port")) {
  429.     dprintf("port=%d ", port);
  430.     params->sin.sin_port = htons(port);
  431.     } else {
  432.     params->sin.sin_port = htons(NFS_PORT); /* XXX should use portmapper */
  433.     }
  434.     dprintf("\n");
  435.  
  436.     /*
  437.      * Assume success
  438.      */
  439.     retval = 1;
  440.  
  441.     /*
  442.      * Try the mount 10 times, sleeping 1/10th of a second between tries.
  443.      */
  444.     tries = 0;
  445.     while (mount(MOUNT_NFS, path, flags, &mount_args) < 0) {
  446.     if (++tries > 10 || errno != EBUSY) {
  447.         /*
  448.          * Mount failed -- notify user and break out.
  449.          */
  450.         perror(path);
  451.         retval = 0;
  452.         break;
  453.     }
  454.     /*
  455.      * Sleep a 1/10th of a second before trying again.
  456.      */
  457.     usleep(100000);
  458.     }
  459.         
  460.     if (retval) {
  461.     /*
  462.      * Now store the entry in /etc/mtab
  463.      */
  464.     dprintf("adding %s to %s\n", fsname, MOUNTED);
  465.  
  466.     mtab = setmntent(MOUNTED, "r+");
  467.     if (addmntent(mtab, &entry)) {
  468.         dprintf("addmntent failed\n");
  469.     }
  470.     endmntent(mtab);
  471.     }
  472.  
  473.     /*
  474.      * Return result
  475.      */
  476.     Rpc_Return(msg, sizeof(retval), (Rpc_Opaque)&retval);
  477. }
  478.  
  479.  
  480. /***********************************************************************
  481.  *                ChildMountLocal
  482.  ***********************************************************************
  483.  * SYNOPSIS:        Mount a prefix on the local prefix daemon
  484.  * CALLED BY:        PREFIX_MOUNT_LOCAL
  485.  * RETURN:        1 if successful
  486.  * SIDE EFFECTS:    None
  487.  *
  488.  * STRATEGY:
  489.  *
  490.  * REVISION HISTORY:
  491.  *    Name    Date        Description
  492.  *    ----    ----        -----------
  493.  *    ardeb    7/10/89        Initial Revision
  494.  *
  495.  ***********************************************************************/
  496. static void
  497. ChildMountLocal(from, msg, len, data, serverData)
  498.     struct sockaddr_in    *from;        /* Source of message */
  499.     Rpc_Message            msg;        /* Message for reply/error */
  500.     int                    len;        /* Length of passed data */
  501.     Rpc_Opaque            data;        /* Parameters */
  502.     Rpc_Opaque            serverData; /* Data we gave (UNUSED) */
  503. {
  504.     ChildData            *params;    /* Parameters for call (addr and
  505.                      * handle and path) */
  506.     struct nfs_args     mount_args; /* Args for the mounting */
  507.     int                    retval;        /* Value to return */
  508.     /*
  509.      * Params extracted from data
  510.      */
  511.     fhandle_t            *handle;    /* Handle the kernel will use */
  512.     char                *path;        /* Local path of prefix */
  513.     int                    flags;        /* Flags for mount call */
  514.  
  515.  
  516.     /*
  517.      * Verify source of message
  518.      */
  519.     if ((ntohs(from->sin_port) != PREFIX_PORT) || !Rpc_IsLocal(from)) {
  520.     Rpc_Error(msg, RPC_ACCESS);
  521.     return;
  522.     }
  523.     
  524.     /*
  525.      * Unpackage parameters
  526.      */
  527.     params  = (ChildData *)data;
  528.     handle  = (fhandle_t *)params->data;
  529.     path    = params->data + sizeof(*handle);
  530.     
  531.     dprintf("ChildMountLocal: path = %s\n", path);
  532.  
  533.     /*
  534.      * Set up nfs_args structure for the mount.
  535.      * All of our mount points are given a timeout of 3 seconds and
  536.      * 4 attempts to contact us. The 3 seconds are because that's
  537.      * how long we'll broadcast looking for a prefix and the 4
  538.      * attempts are to keep the system from grinding to a complete
  539.      * halt if we die (knock on wood...)
  540.      */
  541.     mount_args.addr     = ¶ms->sin;
  542.     mount_args.fh       = handle;
  543.     mount_args.flags    =
  544.     NFSMNT_HOSTNAME|NFSMNT_SOFT|NFSMNT_TIMEO|NFSMNT_RETRANS;
  545.     mount_args.hostname    = MOUNT_NAME;
  546.     mount_args.timeo    = 30;        /* Length of broadcast */
  547.     mount_args.retrans    = 4;        /* # retrans (try four times) */
  548.  
  549. #ifdef NFSMNT_NOAC
  550.     /*
  551.      * SunOS 4.0: Make darn sure the kernel asks us about everything...
  552.      */
  553.     mount_args.flags    |= NFSMNT_NOAC;
  554. #endif /* NFSMNT_NOAC */
  555.  
  556.     /*
  557.      * Mount the prefix READ ONLY -- might as well forestall any
  558.      * calls to do things we can't...
  559.      */
  560.     flags = M_RDONLY;
  561.  
  562. #ifdef M_NEWTYPE
  563.     flags |= M_NEWTYPE;        /* SunOS 4.0 requires this */
  564. #endif /* M_NEWTYPE */
  565.  
  566.     if (mount(MOUNT_NFS, path, flags, &mount_args) < 0) {
  567.     perror(path);
  568.     retval = 0;
  569.     } else {
  570.     retval = 1;
  571.     }
  572.  
  573.     dprintf("return(%d)\n", retval);
  574.     Rpc_Return(msg, sizeof(retval), (Rpc_Opaque)&retval);
  575. }
  576.  
  577.  
  578. /***********************************************************************
  579.  *                ChildUnmount
  580.  ***********************************************************************
  581.  * SYNOPSIS:        Unmount a remote-mounted prefix
  582.  * CALLED BY:        PREFIX_UNMOUNT
  583.  * RETURN:        1 if successful, 0 if not
  584.  * SIDE EFFECTS:    None
  585.  *
  586.  * STRATEGY:
  587.  *
  588.  * REVISION HISTORY:
  589.  *    Name    Date        Description
  590.  *    ----    ----        -----------
  591.  *    ardeb    7/10/89        Initial Revision
  592.  *
  593.  ***********************************************************************/
  594. static void
  595. ChildUnmount(from, msg, len, data, serverData)
  596.     struct sockaddr_in    *from;        /* Source of message */
  597.     Rpc_Message            msg;        /* Message for reply/error */
  598.     int                    len;        /* Length of passed data */
  599.     Rpc_Opaque            data;        /* ChildData with server address,
  600.                      * name, remote directory and local
  601.                      * path */
  602.     Rpc_Opaque            serverData; /* Data we gave (UNUSED) */
  603. {
  604.     ChildData            *params;    /* Our version of data */
  605.     int                    retval;        /* Value to return */
  606.     /*
  607.      * Data extracted from params
  608.      */
  609.     char                *serverName;
  610.     char        *remote;
  611.     char        *path;
  612.  
  613.     if ((ntohs(from->sin_port) != PREFIX_PORT) || !Rpc_IsLocal(from)) {
  614.     Rpc_Error(msg, RPC_ACCESS);
  615.     return;
  616.     }
  617.  
  618.     params      = (ChildData *)data;
  619.     serverName     = params->data;
  620.     remote      = serverName + strlen(serverName) + 1;
  621.     path        = remote + strlen(remote) + 1;
  622.  
  623.     dprintf("ChildUnmount: unmounting %s from %s[%s]: ", path, serverName,
  624.         remote);
  625.  
  626.     /*
  627.      * Try and unmount the thing.
  628.      */
  629.     if (unmount(path) < 0) {
  630.     if (errno == EINVAL) {
  631.         /*
  632.          * EINVAL from unmount means the thing wasn't actually mounted.
  633.          * We want this to appear as a succesful unmount, as it allows
  634.          * the user to explicitly unmount a prefix without our getting
  635.          * confused.
  636.          */
  637.         dprintf("wasn't mounted\n");
  638.         retval = 1;
  639.     } else {
  640.         extern int sys_nerr;
  641.         extern char *sys_errlist[];
  642.  
  643.         dprintf("error: %s\n",
  644.             errno > sys_nerr ? "Unknown" : sys_errlist[errno]);
  645.         retval = 0;
  646.     }
  647.     } else {
  648.     /*
  649.      * Need to remove from /etc/mtab and tell the remote mount daemon
  650.      * the thing's no longer mounted.
  651.      */
  652.     FILE            *mtab;        /* Old table of mounted systems */
  653.     FILE            *nmtab;        /* New table of mounted systems */
  654.     struct mntent    *entry;        /* Current entry in same */
  655.     char            tmtab[20];  /* Name for new table */
  656.     char            fsname[128];/* System being unmounted */
  657.     
  658.     dprintf("successful...contacting mount daemon: ");
  659.     if (!ChildCallMountd(¶ms->sin, serverName, remote, MOUNTPROC_UMNT,
  660.                   xdr_void, NULL))
  661.     {
  662.         dprintf("failed\n");
  663.     } else {
  664.         dprintf("successful\n");
  665.     }
  666.  
  667.     /*
  668.      * Remove the prefix from the table of mounted systems by
  669.      * copying all entries except the one just unmounted to a new mtab.
  670.      * Filename formed this way to deal with gcc storing strings in
  671.      * text (of which we approve).
  672.      */
  673.     strcpy(tmtab, MOUNTED);
  674.     strcat(tmtab, "XXXXXX");
  675.     mktemp(tmtab);
  676.     
  677.     sprintf(fsname, "%s:%s", serverName, remote);
  678.     
  679.     mtab = setmntent(MOUNTED, "r");
  680.     nmtab = setmntent(tmtab, "w");
  681.     
  682.     while ((entry = getmntent(mtab)) != NULL) {
  683.         if (strcmp(entry->mnt_fsname, fsname) != 0) {
  684.         addmntent(nmtab, entry);
  685.         }
  686.     }
  687.     
  688.     /*
  689.      * Close both
  690.      */
  691.     endmntent(mtab);
  692.     endmntent(nmtab);
  693.     
  694.     /*
  695.      * Use atomic rename to replace old mtab.
  696.      */
  697.     rename(tmtab, MOUNTED);
  698.  
  699.     /*
  700.      * Success.
  701.      */
  702.     retval = 1;
  703.     }
  704.  
  705.     Rpc_Return(msg, sizeof(retval), (Rpc_Opaque)&retval);
  706. }
  707.          
  708.  
  709. /***********************************************************************
  710.  *                ChildUnmountLocal
  711.  ***********************************************************************
  712.  * SYNOPSIS:        Unmount a prefix from local daemon. This is
  713.  *                just to be safe, you understand...
  714.  * CALLED BY:        PREFIX_UNMOUNT_LOCAL
  715.  * RETURN:        1 if successful
  716.  * SIDE EFFECTS:    None
  717.  *
  718.  * STRATEGY:
  719.  *
  720.  * REVISION HISTORY:
  721.  *    Name    Date        Description
  722.  *    ----    ----        -----------
  723.  *    ardeb    7/10/89        Initial Revision
  724.  *
  725.  ***********************************************************************/
  726. static void
  727. ChildUnmountLocal(from, msg, len, data, serverData)
  728.     struct sockaddr_in    *from;        /* Source of message */
  729.     Rpc_Message            msg;        /* Message for reply/error */
  730.     int                    len;        /* Length of parameters */
  731.     Rpc_Opaque            data;        /* Parameters (path to unmount) */
  732.     Rpc_Opaque            serverData; /* Data we gave (UNUSED) */
  733. {
  734.     int                    retval;        /* Return value */
  735.  
  736.     if ((ntohs(from->sin_port) != PREFIX_PORT) || !Rpc_IsLocal(from)) {
  737.     Rpc_Error(msg, RPC_ACCESS);
  738.     } else {
  739.     dprintf("ChildUnmountLocal: unmounting %s...", (char *)data);
  740.     retval = unmount((char *)data);
  741.     if (retval < 0) {
  742.         if (errno == EINVAL) {
  743.         /*
  744.          * If it wasn't mounted anyway, we're happy.
  745.          */
  746.         retval = 0;
  747.         } else {
  748.         retval = 0;
  749.         perror((char *)data);
  750.         }
  751.     } else {
  752.         retval = 1;
  753.     }
  754.     dprintf("return(%d)\n", retval);
  755.     Rpc_Return(msg, sizeof(retval), &retval);
  756.     }
  757. }
  758.     
  759.  
  760. /***********************************************************************
  761.  *                Child_Init
  762.  ***********************************************************************
  763.  * SYNOPSIS:        Initialize this module
  764.  * CALLED BY:        BeFiendish
  765.  * RETURN:        1 if successful.
  766.  * SIDE EFFECTS:    A new process is created.
  767.  *
  768.  * STRATEGY:
  769.  *    - Create the socket over which communication will pass
  770.  *    - Fetch the socket's address
  771.  *    - Create mountdSock
  772.  *    - Fork. If parent, close childSock and mountdSock and return 1
  773.  *    - Child: run RPC system.
  774.  *
  775.  * REVISION HISTORY:
  776.  *    Name    Date        Description
  777.  *    ----    ----        -----------
  778.  *    ardeb    7/ 9/89        Initial Revision
  779.  *
  780.  ***********************************************************************/
  781. int
  782. Child_Init()
  783. {
  784.     int                    len;
  785.     struct sockaddr_in    sin;
  786.     unsigned short      port;
  787.     int                    err;
  788.     
  789.     /*
  790.      * XXX: Use socketpair(AF_UNIX)? Not sure what it would do with a
  791.      * sendto, though, and I'd have to rewrite the RPC system to understand
  792.      * AF_UNIX if it couldn't take it. Advantage is the channel would be
  793.      * private.
  794.      */
  795.     childSock = Rpc_UdpCreate(TRUE, 0);
  796.     if (childSock < 0) {
  797.     perror("Rpc_UdpCreate(child)");
  798.     return(0);
  799.     }
  800.  
  801.     len = sizeof(childAddr);
  802.     if (getsockname(childSock, &childAddr, &len) < 0) {
  803.     perror("getsockname(child)");
  804.     return(0);
  805.     }
  806.     childAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  807.     
  808.     /*
  809.      * Create and initialize a socket over which we can communicate with
  810.      * a remote mount daemon. Such a socket must have an address in the
  811.      * range 512 - 1023 (the privileged area of the UDP address space) in
  812.      * order for the remote daemon to accept our credentials.
  813.      * NOTE: can't use Rpc_UdpCreate since that will bind only one port or
  814.      * any, not any of a range.
  815.      */
  816.     mountdSock = socket(AF_INET, SOCK_DGRAM, 0);
  817.     if (mountdSock < 0) {
  818.     perror("socket(mountd)");
  819.     return(0);
  820.     }
  821.  
  822. #define MAX_PRIV (IPPORT_RESERVED-1)
  823. #define MIN_PRIV (IPPORT_RESERVED/2)
  824.  
  825.     /*
  826.      * Initialize constant part of address: family and address
  827.      */
  828.     bzero(&sin, sizeof sin);
  829.     get_myaddress(&sin);
  830.     sin.sin_family = AF_INET;
  831.  
  832.     /*
  833.      * Loop over all untaken privileged ports (i.e. upper half of range),
  834.      * trying to bind the socket to each in turn. If succeed, end up
  835.      * with err being zero and the socket bound.
  836.      */
  837.     for (err = -1, port = MAX_PRIV; err && port >= MIN_PRIV; port--) {
  838.     sin.sin_port = htons(port);
  839.     err = bind(mountdSock, &sin, sizeof(sin));
  840.     }
  841.  
  842.     if (err == -1) {
  843.     perror("binding mountd socket");
  844.     return(0);
  845.     }
  846.  
  847.     /*
  848.      * All set -- create the child process
  849.      */
  850.     switch(childID = fork()) {
  851.     case 0:
  852.         /*
  853.          * Don't pay attention to anything else
  854.          */
  855.         Rpc_Reset();
  856.         (void)close(prefixSock);
  857.         /*
  858.          * Register the three servers. Note that even though we
  859.          * pass binary data, there's no need for swapping, since the
  860.          * communication happens on the local machine.
  861.          */
  862.         Rpc_ServerCreate(childSock, PREFIX_MOUNT, ChildMount,
  863.                  NULL, NULL, NULL);
  864.         Rpc_ServerCreate(childSock, PREFIX_MOUNT_LOCAL, ChildMountLocal,
  865.                  NULL, NULL, NULL);
  866.         Rpc_ServerCreate(childSock, PREFIX_UNMOUNT, ChildUnmount,
  867.                  NULL, NULL, NULL);
  868.         Rpc_ServerCreate(childSock, PREFIX_UNMOUNT_LOCAL,ChildUnmountLocal,
  869.                  NULL, NULL, NULL);
  870.         /*
  871.          * Perform similar std stream manipulations to sibling to
  872.          * allow logging and invocation by rshd. Again, we change our
  873.          * process group so opening the console doesn't make it our
  874.          * controlling terminal.
  875.          */
  876.         setpgrp(0, getpid());
  877.         freopen("/dev/console", "w", stderr);
  878.         (void)close(0);
  879.         (void)close(1);
  880.         
  881.         /*
  882.          * Run the RPC system -- never returns.
  883.          */
  884.         dprintf("child prefix daemon alive and running...\n");
  885.         Rpc_Run();
  886.     case -1:
  887.         perror("fork(child)");
  888.         return(0);
  889.     default:
  890.         /*
  891.          * Close the two sockets and return success
  892.          */
  893.         (void)close(mountdSock);
  894.         (void)close(childSock);
  895.         return(1);
  896.     }
  897. }
  898.  
  899.  
  900. /***********************************************************************
  901.  *                Child_Call
  902.  ***********************************************************************
  903.  * SYNOPSIS:        Issue a call to the child process.
  904.  * CALLED BY:        EXTERNAL
  905.  * RETURN:        1 if the call succeeded, 0 if not
  906.  * SIDE EFFECTS:    None
  907.  *
  908.  * STRATEGY:
  909.  *
  910.  * REVISION HISTORY:
  911.  *    Name    Date        Description
  912.  *    ----    ----        -----------
  913.  *    ardeb    7/ 9/89        Initial Revision
  914.  *
  915.  ***********************************************************************/
  916. int
  917. Child_Call(pp, proc)
  918.     Prefix      *pp;        /* Prefix for which to call */
  919.     Rpc_Proc       proc;        /* Procedure to invoke (PREFIX_MOUNT or
  920.                  * PREFIX_UNMOUNT or PREFIX_MOUNT_LOCAL) */
  921. {
  922.     struct timeval  retry;  /* Retransmission interval */
  923.     Rpc_Stat    status;        /* Result of call */
  924.     int            success;    /* Return data: non-zero if operation
  925.                  * succeeded */
  926.     ChildData    data;        /* Data to pass to child */
  927.     char        *cp;        /* Current position in data.data */
  928.  
  929.     retry.tv_sec = 2;
  930.     retry.tv_usec = 0;
  931.     
  932.     switch (proc) {
  933.     case PREFIX_MOUNT:
  934.     case PREFIX_UNMOUNT:
  935.     {
  936.         /*
  937.          * Both of these require the parameters for the remote
  938.          * machine.
  939.          */
  940.         int            len;        /* Length remaining in data.data */
  941.         int            slen;        /* Length of current string */
  942.         
  943.         /*
  944.          * Pass the server's address
  945.          */
  946.         data.sin = pp->server;
  947.         
  948.         /*
  949.          * Set up vars...
  950.          */
  951.         len = CHILD_MAX_DATA;
  952.         cp = data.data;
  953.         
  954.         /*
  955.          * Server's name comes first
  956.          */
  957.         slen = strlen(pp->serverName);
  958.         if (slen <= len) {
  959.         strcpy(cp, pp->serverName);
  960.         cp += slen + 1;
  961.         len -= slen+1;
  962.         } else {
  963.         return(0);
  964.         }
  965.         
  966.         /*
  967.          * Then the remote directory name
  968.          */
  969.         slen = strlen(pp->remote);
  970.         if (slen <= len) {
  971.         strcpy(cp, pp->remote);
  972.         cp += slen + 1;
  973.         len -= slen+1;
  974.         } else {
  975.         return(0);
  976.         }
  977.         
  978.         /*
  979.          * Then the local directory name
  980.          */
  981.         slen = strlen(pp->path);
  982.         if (slen <= len) {
  983.         strcpy(cp, pp->path);
  984.         cp += slen + 1;
  985.         len -= slen+1;
  986.         } else {
  987.         return(0);
  988.         }
  989.         
  990.         /*
  991.          * If mounting, pass the mount options too.
  992.          */
  993.         if (proc == PREFIX_MOUNT) {
  994.         slen = strlen(pp->options);
  995.         if (slen <= len) {
  996.             strcpy(cp, pp->options);
  997.             cp += slen + 1;
  998.             len -= slen+1;
  999.         } else {
  1000.             return(0);
  1001.         }
  1002.         }
  1003.         break;
  1004.     }
  1005.     case PREFIX_MOUNT_LOCAL:
  1006.         /*
  1007.          * Just need to pass prefixMountAddr, a handle and the local
  1008.          * directory.
  1009.          */
  1010.  
  1011.         data.sin = prefixMountAddr;
  1012.  
  1013.         PrefixToHandle(pp, data.data);
  1014.  
  1015.         cp = data.data + sizeof(fhandle_t);
  1016.         strcpy(cp, pp->path);
  1017.         cp += strlen(cp) + 1;
  1018.         break;
  1019.     case PREFIX_UNMOUNT_LOCAL:
  1020.         /*
  1021.          * Just need to pass the path.
  1022.          */
  1023.         strcpy((char *)&data, pp->path);
  1024.  
  1025.         cp = (char *)&data + strlen(pp->path) + 1;
  1026.         break;
  1027.     default:
  1028.         /*
  1029.          * What the heck?
  1030.          */
  1031.         return(0);
  1032.     }
  1033.     
  1034.     /*
  1035.      * Issue the call, passing only as much data as are available.
  1036.      * We lock the prefix in the meantime b/c this call implies a change
  1037.      * of state that should not be used until the call completes. Because
  1038.      * of the nature of our rpc system, however, we could very well get
  1039.      * a request for the prefix while waiting for this call. Anything that
  1040.      * depends on whether a prefix is mounted obeys the locking protocol.
  1041.      */
  1042.     PrefixLock(pp);
  1043.     status = Rpc_Call(prefixSock, &childAddr, proc,
  1044.               cp - (char *)&data, (Rpc_Opaque)&data,
  1045.               sizeof(success), (Rpc_Opaque)&success,
  1046.               NUM_RETRIES, &retry);
  1047.     PrefixUnlock(pp);
  1048.  
  1049.     if (status != RPC_SUCCESS) {
  1050.     /*
  1051.      * Call didn't get through -- return error.
  1052.      */
  1053.     dprintf("Child_Call: %s\n", Rpc_ErrorMessage(status));
  1054.     return(0);
  1055.     } else {
  1056.     /*
  1057.      * Return what we were told to return.
  1058.      */
  1059.  
  1060.     return(success);
  1061.     }
  1062. }
  1063.  
  1064.  
  1065. /***********************************************************************
  1066.  *                Child_MountSpecial
  1067.  ***********************************************************************
  1068.  * SYNOPSIS:        Mount a special prefix locally.
  1069.  * CALLED BY:        BeFiendish to mount MOUNT_DIR
  1070.  * RETURN:        Nothing
  1071.  * SIDE EFFECTS:    None
  1072.  *
  1073.  * STRATEGY:
  1074.  *    Call PREFIX_MOUNT_LOCAL, passing it prefixMountAddr, but with
  1075.  *    the given port and storing the path as the handle, rather than
  1076.  *    a prefix address.
  1077.  *
  1078.  * REVISION HISTORY:
  1079.  *    Name    Date        Description
  1080.  *    ----    ----        -----------
  1081.  *    ardeb    7/10/89        Initial Revision
  1082.  *
  1083.  ***********************************************************************/
  1084. int
  1085. Child_MountSpecial(port, path)
  1086.     unsigned short  port;       /* Port kernel should use */
  1087.     char            *path;      /* Directory to mount */
  1088. {
  1089.     ChildData        data;       /* Data to pass */
  1090.     char            *cp;        /* Points past last byte of data */
  1091.     int                success;    /* Return value */
  1092.     struct timeval  retry;      /* Retransmission interval */
  1093.     Rpc_Stat        status;    /* Status of call */
  1094.  
  1095.     /*
  1096.      * Address is the same as the prefix address, except for the port number
  1097.      */
  1098.     data.sin = prefixMountAddr;
  1099.     data.sin.sin_port = htons(port);
  1100.  
  1101.     /*
  1102.      * Set up the handle to use (type PH_SPECIAL -- if we get more,
  1103.      * we'll need to add more info).
  1104.      */
  1105.     bzero(data.data, sizeof(fhandle_t));
  1106.     ((PrefixHandle *)data.data)->type = PH_SPECIAL;
  1107.     cp = data.data + sizeof(fhandle_t);
  1108.  
  1109.     /*
  1110.      * Pass the path as the mount point
  1111.      */
  1112.     strcpy(cp, path);
  1113.     cp += strlen(path) + 1;
  1114.  
  1115.     /*
  1116.      * 1-second retransmission interval
  1117.      */
  1118.     retry.tv_sec = 1;
  1119.     retry.tv_usec = 0;
  1120.  
  1121.     /*
  1122.      * Call the child...
  1123.      */
  1124.     status = Rpc_Call(prefixSock, &childAddr, PREFIX_MOUNT_LOCAL,
  1125.              cp - (char *)&data, (Rpc_Opaque)&data,
  1126.              sizeof(success), (Rpc_Opaque)&success,
  1127.              NUM_RETRIES, &retry);
  1128.  
  1129.     if (status != RPC_SUCCESS) {
  1130.     perror("Rpc_Call");
  1131.     dprintf("Child_MountSpecial: %s\n", Rpc_ErrorMessage(status));
  1132.     return(0);
  1133.     } else {
  1134.     return(success);
  1135.     }
  1136. }
  1137.  
  1138.  
  1139. /***********************************************************************
  1140.  *                Child_Kill
  1141.  ***********************************************************************
  1142.  * SYNOPSIS:        Blow away the child process
  1143.  * CALLED BY:        main
  1144.  * RETURN:        Nothing
  1145.  * SIDE EFFECTS:    The child be savagely, brutally murdered
  1146.  *
  1147.  * STRATEGY:
  1148.  *
  1149.  * REVISION HISTORY:
  1150.  *    Name    Date        Description
  1151.  *    ----    ----        -----------
  1152.  *    ardeb    7/10/89        Initial Revision
  1153.  *
  1154.  ***********************************************************************/
  1155. void
  1156. Child_Kill()
  1157. {
  1158.     kill(childID, 9);
  1159. }
  1160.